﻿using System.Text.Json.Serialization.Metadata;
using DimensionsHelper.Client.Navigation;
using DimensionsHelper.Common.Contracts.TableFormatter;
using DimensionsHelper.Common.Contracts.TableFormatter.Options;
using DimensionsHelper.Common.Contracts.Excel;
using DimensionsHelper.Common.Utils;

namespace DimensionsHelper.Client.ViewModels.CsvFormatter;

public class CsvFormatterViewModel(IServiceProvider serviceProvider)
    : JsonLoaderViewModel<TableFormatterOptions>(serviceProvider)
{
    public override string Section => "CSV格式化器";

    protected override JsonTypeInfo<TableFormatterOptions> LoadingTypeInfo =>
        ServiceJsonContext.Default.TableFormatterOptions;

    public override string HistoryJsonSettingName => "CsvFormatterHistoricalSettings";

    private static NavigationKeyBuilder KeyBuilder { get; } = new(null, "CsvFormatter");

    protected override RunnableContainer GetRunnableContainer()
    {
        ITableFormatter formatter = ServiceProvider.GetRequiredService<ITableFormatter>();

        return new RunnableContainer<CsvFormatterViewModel, ITableFormatter, TableFormatterOptions>(this, formatter,
            (csvFormatter, provider, token) =>
            {
                (string OutputFileName, TableInputFileInfo[])[] groupFiles = provider
                    .GetRequiredService<CsvFileGroupListViewModel>()
                    .Where(viewModel => !string.IsNullOrEmpty(viewModel.OutputFileName))
                    .Select(viewModel => (viewModel.OutputFileName, viewModel.ToCsvInputFileInfoArray()))
                    .ToArray();

                if (groupFiles.Length == 0)
                {
                    csvFormatter.ReportService?.Error(ProjectErrorMessages.ProjectInputFileIsNotSelected);
                    return;
                }

                bool correctNumber = csvFormatter.Settings.Table.CorrectTableNumber;

                foreach ((string outputFileName, TableInputFileInfo[] inputFiles) in groupFiles)
                {
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }

                    IExcelWorkbookOperator destination =
                        ServiceProvider.GetRequiredService<IExcelWorkbookOperator>();

                    if (inputFiles.Any(info => info.InsertFiles.Count > 0) &&
                        !csvFormatter.Settings.Table.CorrectTableNumber)
                    {
                        csvFormatter.ReportService?.Log("由于配置了插入的文件，已将'CorrectTableNumber'设置为'true'。");
                    }

                    try
                    {
                        destination.Create(outputFileName);
                        formatter.Execute(destination, inputFiles, token);
                    }
                    catch (Exception e)
                    {
                        csvFormatter.ReportService?.Error(e.Message);
                    }
                    finally
                    {
                        destination.Close();
                    }

                    csvFormatter.Settings.Table.CorrectTableNumber = correctNumber;
                }
            });
    }

    public override void LoadOption(TableFormatterOptions source)
    {
        // Replace
        ServiceProvider
            .GetRequiredKeyedService<StringPairViewModel>(KeyBuilder.ServiceKey(ServiceKeys.Replacement))
            .FromDictionary(source.TextReplacements);
        // Table
        TableStyleOptionsViewModel tableStyle = ServiceProvider.GetRequiredService<TableStyleOptionsViewModel>();
        tableStyle.LoadOption(source.Table);
        // Sig
        tableStyle.Sig.LoadOption(source.Sig);
    }

    public override bool TryWriteOption(TableFormatterOptions target)
    {
        // Replace
        ServiceProvider
            .GetRequiredKeyedService<StringPairViewModel>(KeyBuilder.ServiceKey(ServiceKeys.Replacement))
            .ToDictionary(target.TextReplacements);
        // Table
        TableStyleOptionsViewModel tableStyle = ServiceProvider.GetRequiredService<TableStyleOptionsViewModel>();
        return tableStyle.TryWriteOption(target.Table) && tableStyle.Sig.TryWriteOption(target.Sig);
    }
}